from fastapi import APIRouter, HTTPException, Depends, UploadFile, File, Form, Query, Request
from fastapi.responses import Response, JSONResponse
from typing import Dict, Optional
from app.services.audio_service import AudioService
from app.core.logger import logger
from app.core.exceptions import DifyAPIError

router = APIRouter(tags=["音频处理"])

# 依赖项：创建AudioService实例
def get_audio_service():
    return AudioService()

@router.post("/audio-to-text", response_model=Dict)
async def audio_to_text(
    file: UploadFile = File(..., description="语音文件"),
    user: str = Form(..., description="用户ID"),
    audio_service: AudioService = Depends(get_audio_service)
):
    """
    语音转文字
    
    将上传的音频文件转换为文本。支持格式：['mp3', 'mp4', 'mpeg', 'mpga', 'm4a', 'wav', 'webm']
    文件大小限制：15MB
    """
    logger.info(f"语音转文本请求: filename={file.filename}, user={user}, content_type={file.content_type}")
    
    # 检查文件格式
    allowed_formats = ['mp3', 'mp4', 'mpeg', 'mpga', 'm4a', 'wav', 'webm']
    file_ext = file.filename.split('.')[-1].lower()
    if file_ext not in allowed_formats:
        logger.warning(f"不支持的文件格式: {file_ext}")
        raise HTTPException(status_code=415, detail=f"不支持的文件格式：{file_ext}，支持的格式：{', '.join(allowed_formats)}")
    
    try:
        # 调用语音转文本服务
        logger.info("开始处理语音转文本请求")
        result = await audio_service.speech_to_text(
            audio_file=file,
            user=user
        )
        
        # 确保结果包含text字段
        if "text" not in result:
            logger.warning("语音识别结果中没有text字段，添加空字段")
            result["text"] = ""
            
        # 如果是备选引擎处理的结果，添加标记
        if result.get("is_fallback"):
            logger.info("返回备选引擎处理的结果")
            # 可以保留is_fallback标记，或者在这里移除它
            # 如果API规范不允许额外字段，可以移除
            # result.pop("is_fallback", None)
            # result.pop("audio_info", None)
            
        logger.info(f"语音转文本完成，结果长度: {len(result.get('text', ''))}")
        return result
        
    except DifyAPIError as e:
        error_detail = e.detail if hasattr(e, 'detail') and e.detail else "语音转文本处理失败(无详细信息)"
        status_code = e.status_code if hasattr(e, 'status_code') and e.status_code else 500
        logger.error(f"语音转文本失败 (DifyAPIError): {error_detail}")
        return JSONResponse(
            status_code=status_code,
            content={"detail": error_detail}
        )
    except ValueError as e:
        error_msg = str(e) or "参数验证错误(无详细信息)"
        logger.error(f"语音转文本参数错误: {error_msg}")
        raise HTTPException(status_code=400, detail=error_msg)
    except Exception as e:
        error_msg = str(e) or "未知错误"
        logger.error(f"语音转文本失败: {error_msg}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"语音转文本失败: {error_msg}")

@router.post("/text-to-audio")
@router.get("/text-to-audio")
async def text_to_audio(
    request: Request,
    text: Optional[str] = None,
    message_id: Optional[str] = None,
    user: Optional[str] = None,
    audio_service: AudioService = Depends(get_audio_service)
):
    """
    文本转语音
    
    将文本转换为语音文件。可以通过message_id或直接提供text进行转换。
    如果同时提供message_id和text，优先使用message_id。
    
    此接口同时支持:
    1. POST请求+表单提交(application/x-www-form-urlencoded或multipart/form-data)
    2. GET请求+URL参数
    
    返回的是二进制音频数据，可以直接在浏览器中播放，或通过audio标签引用。
    """
    # 根据请求类型获取参数
    if request.method == "GET":
        # 如果没有提供参数，从查询参数中获取
        if text is None:
            text = request.query_params.get("text")
        if message_id is None:
            message_id = request.query_params.get("message_id")
        if user is None:
            user = request.query_params.get("user")
    else:  # POST
        # 表单请求，后续会进行处理
        try:
            # 尝试从表单中读取参数
            form_data = await request.form()
            if text is None:
                text = form_data.get("text")
            if message_id is None:
                message_id = form_data.get("message_id")
            if user is None:
                user = form_data.get("user")
        except:
            # 如果不是表单请求，可能是JSON请求
            try:
                json_data = await request.json()
                if text is None:
                    text = json_data.get("text")
                if message_id is None:
                    message_id = json_data.get("message_id")
                if user is None:
                    user = json_data.get("user")
            except:
                # 如果既不是表单也不是JSON，可能参数在查询字符串中
                if text is None:
                    text = request.query_params.get("text")
                if message_id is None:
                    message_id = request.query_params.get("message_id")
                if user is None:
                    user = request.query_params.get("user")
    
    logger.info(f"文本转语音请求: text={text[:20] if text else None}..., message_id={message_id}, user={user}")
    
    if not message_id and not text:
        logger.warning("文本转语音请求缺少必要参数: 未提供message_id或text")
        raise HTTPException(status_code=400, detail="必须提供message_id或text参数")
    
    if not user:
        logger.warning("文本转语音请求缺少必要参数: 未提供user")
        raise HTTPException(status_code=400, detail="必须提供user参数")
    
    try:
        # 调用文本转语音服务
        logger.info("开始处理文本转语音请求")
        result = await audio_service.text_to_speech(
            text=text,
            user=user,
            message_id=message_id
        )
        
        # 处理返回的音频数据
        audio_content = result.get("audio_content")
        content_type = result.get("content_type", "audio/mp3")
        
        if audio_content:
            # 验证音频数据非空且有效
            if len(audio_content) < 100:
                logger.warning(f"收到的音频数据太小，可能无效: {len(audio_content)} 字节")
                return JSONResponse(
                    status_code=500,
                    content={"detail": f"生成的音频数据无效，数据大小: {len(audio_content)} 字节"}
                )
            
            logger.info(f"文本转语音完成，返回音频数据，大小: {len(audio_content)} 字节，类型: {content_type}")
            return Response(
                content=audio_content,
                media_type=content_type,
                # 不设置Content-Disposition头，这样浏览器会直接播放而不是下载
                headers={
                    # 添加CORS相关头，支持跨域播放
                    "Access-Control-Allow-Origin": "*",
                    "Accept-Ranges": "bytes"
                }
            )
        else:
            # 如果没有音频数据，尝试从URL获取
            audio_url = result.get("audio_url")
            if audio_url:
                logger.info(f"文本转语音完成，返回音频URL: {audio_url}")
                return JSONResponse(content={"audio_url": audio_url})
            else:
                logger.error("文本转语音返回结果中没有音频数据或URL")
                return JSONResponse(
                    status_code=500,
                    content={"detail": "无法获取音频数据，请检查API返回"}
                )
                
    except DifyAPIError as e:
        error_detail = e.detail if hasattr(e, 'detail') and e.detail else "文本转语音处理失败(无详细信息)"
        status_code = e.status_code if hasattr(e, 'status_code') and e.status_code else 500
        logger.error(f"文本转语音失败 (DifyAPIError): {error_detail}")
        # 确保返回正确的状态码
        if status_code == 404 and "未知错误" in error_detail:
            # 如果是404 Not Found但实际是API调用错误，改为500
            status_code = 500
        
        return JSONResponse(
            status_code=status_code,
            content={"detail": error_detail}
        )
    except ValueError as e:
        error_msg = str(e) or "参数验证错误(无详细信息)"
        logger.error(f"文本转语音参数错误: {error_msg}")
        raise HTTPException(status_code=400, detail=error_msg)
    except Exception as e:
        error_msg = str(e) or "未知错误"
        logger.error(f"文本转语音失败: {error_msg}", exc_info=True)
        # 确保返回500状态码而不是404
        return JSONResponse(
            status_code=500,
            content={"detail": f"文本转语音失败: {error_msg}"}
        )
